/**
 *
 * @param table {Table}
 * @param auth {boolean} 接口是否需要鉴权
 * @param uninstall {boolean} 是否在生成代码时注释该方法，用于备用
 * @returns {string}
 */
const forEach = (table, auth = false, uninstall = false) => {
  const {
    idType,
    comment,
    names: {TabName}
  } = table
  return `// <-
    /**
     * ${comment} 循环查询列表，使用 id 正序排列，用于批处理数据，类似分页查询批量导出。
     * <pre>
     * 注意：
     *   这里必须使用 id 排序(正序|倒序)，否则会导致数据重复查询，也可能漏掉一部分数据。
     *   循环禁止包含在事务内，避免数据库大批量操作数据导致锁表，请使用 @Transactional(readOnly = true, propagation = Propagation.NEVER)
     *   如果业务允许，跑批时每一条数据都捕获异常且新起一个新事务 @Transactional(propagation = Propagation.REQUIRES_NEW)， 避免一条数据异常引起所有数据回滚
     * </pre>
     *
     * @param listConsumer List<${TabName}> 查询结果
     * @param where        IWhere.QdslWhere 查询条件
     * @param exps         Expression 查询字段
     */
    default void forEach(final Consumer<List<${TabName}>> listConsumer,
                         final IWhere.QdslWhere where,
                         final Expression<?>... exps
    ) {
        ${idType} id = null;
        final int limit = Limit.L1000.value;
        List<${TabName}> list;
        final Expression<?>[] columns = Optional.ofNullable(exps)
                .filter(arr -> arr.length > 0)
                .orElseGet(${TabName}::allColumnAppends);
        do {
            list = getQueryFactory()
                    .select(Projections.bean(${TabName}.class, columns))
                    .from(table)
                    .where(Optional.ofNullable(id).map(table.id::gt).orElse(null))
                    .where(where.toPredicate())
                    .orderBy(table.id.asc())
                    .limit(limit)
                    .fetch();
            if (!list.isEmpty()) {
                id = Objects.requireNonNull(list.get(list.size() - 1).getId());
                listConsumer.accept(list);
            }
        } while (Objects.equals(list.size(), limit));
    }
`.split('\n')
    .map(row => (uninstall ? '//' : '') + row)
    .join('\n')
}
export const forEachOpenInstall = table => forEach(table)
export const forEachOpenUninstall = table => forEach(table, false, true)

export const forEachAuthInstall = table => forEach(table, true, false)
export const forEachAuthUninstall = table => forEach(table, true, true)
